const {
  validate
} = require('schema-utils')
const schema = require('./schema.json')
const path = require('path')
const fs = require('fs')
const {
  promisify
} = require('util')
const readFile = promisify(fs.readFile)
// 忽略某些文件库
const globby = require('globby')
const webpack = require('webpack')
const {
  Compilation
} = require('webpack')
const {
  RawSource
} = webpack.sources
module.exports = class CopyWebpackPlugin {
  constructor(options = {}) {
    validate(schema, options, {
      name: 'CopyWebpackPlugin'
    })
    this.options = options
  }
  apply(compiler) {
    // 初始化 compilation
    compiler.hooks.thisCompilation.tap('CopyWebpackPlugin', (compilation) => {
      // 添加资源
      compilation.hooks.additionalAssets.tapAsync('CopyWebpackPlugin', async (cb) => {
        // 将from 复制到 to
        // 1 忽略 ignore 文件
        const {
          from,
          ignore
        } = this.options;
        const to = this.options.to ? this.options.to : '.';
        const paths = await globby([from, `!${[...ignore]}`])
        // 2 读取from资源 map 方法并不能异步等待
        const files = await Promise.all( // files[]
          paths.map(async absolutePath => {
            // 读取文件
            const data = await readFile(absolutePath)
            // 获取文件名
            const relativePath = path.basename(absolutePath)
            const filename = path.join(to,relativePath)
            return {
              //文件数据
              data,
              //文件名
              filename
            }
          })
        )
        // 3生成webpack格式资源
        const assets = files.map(file => {
          const source = new RawSource(file.data)
          return {
            source,
            filename: file.filename
          }
        })
        // 4 添加到compilation中 输出
        assets.map(asset => {
          compilation.emitAsset(asset.filename, asset.source)
        })
  
        cb();
      })
    })
  }
}